import feedparser, urllib, re, sys
from youtubeDL import FileDownloader, YoutubeIE, MetacafeIE, YoutubePlaylistIE, DownloadError
import threading
from Queue import Queue
import os


def retrieve_playlist(username):
	playlists_url = 'http://gdata.youtube.com/feeds/api/users/%s/playlists' %username
	feed = feedparser.parse(playlists_url)
	playlists = []
	for en in feed.entries:
		title = en.title
		id_num = en.id.split('/')[-1]
		pages = gen_playlist_pages(id_num)
		playlists.append(dict(title=title, id_num=id_num, pages=pages))
	return playlists


def gen_playlist_pages(id_num):
	playlist_pages = []
	page = 'http://gdata.youtube.com/feeds/api/playlists/%s' % id_num
	pages = []
	for i in range(4):
		params = urllib.urlencode({'start-index':1+50*i, 'max-results':50})
		_page = '%s?%s' % (page, params)
		pages.append(_page)
	return pages

def get_video_links_from_playlists(playlists):
	video_lists = []
	for pl in playlists:
		video_links = []
		for p in pl['pages']:
			feed = feedparser.parse(p)
			for en in feed.entries:
				if re.search(r'watch',en.link):
					video_links.append(en.link)
		pl.update(dict(video_links=video_links))
		video_lists.append(pl)
	return video_lists

def download_list_videos(video_lists, queue):
	for vl in video_lists:
		outtmpl = vl.get('title','no_playlist_title') + u'/%(stitle)s-%(id)s.%(ext)s'
		for video_url in vl.get('video_links'):
			download_video(video_url, queue, outtmpl)
	queue.put(False, 1)

def download_and_play(video_lists):
	q = Queue(32)
	threads = []
	dt = PDThread(func=download_list_videos, args=(video_lists,q))
	pt = PDThread(func=play_video, args=(q,))
	threads.extend([dt, pt])
	for t in threads:
		t.start()
	for t in threads:
		t.join()

def download_video(video_url, queue, outtmpl=''):
	fd = FileDownloader({'outtmpl': outtmpl})
	youtube_ie = YoutubeIE()
	metacafe_ie = MetacafeIE(youtube_ie)
	youtube_pl_ie = YoutubePlaylistIE(youtube_ie)
	fd.add_info_extractor(youtube_pl_ie)
	fd.add_info_extractor(metacafe_ie)
	fd.add_info_extractor(youtube_ie)
	try:
		retcode = fd.download([video_url])
		if retcode == 0:
			queue.put(fd.filename, 1)
		else:
			queue.put(None, 1)
	except DownloadError:
		# yes, we should handle this... maybe later
		pass

def play_video(queue):
	while 1:
		filename = queue.get(1)
		if filename is False:
			break
		elif filename is None:
			print "Video download failed!"
		else:
			command = 'vlc %s vlc:quit' %filename
			os.system(command)

class PDThread(threading.Thread):
	def __init__(self, func, args):
		threading.Thread.__init__(self)
		self.func = func
		self.args = args
	
	def run(self):
		self.res = apply(self.func, self.args)

if __name__ == '__main__':
	pls = retrieve_playlist('your_user_name_here')
	video_list = get_video_links_from_playlists(pls)
	download_and_play(video_list)


